package com.zy.explore.search.application.service;

import cn.hutool.core.lang.UUID;
import com.alibaba.excel.util.CollectionUtils;
import com.google.common.collect.Lists;
import com.zy.explore.search.domain.solr.entity.Article;
import com.zy.explore.search.domain.solr.repository.ArticleRepository;
import com.zy.explore.search.infrastructure.util.DataBeanUtil;
import com.zy.explore.search.interfaces.frm.ArticleQueryFrm;
import com.zy.explore.search.interfaces.frm.ArticleSaveFrm;
import com.zy.explore.search.interfaces.frm.CommonIdFrm;
import com.zy.explore.search.interfaces.frm.CommonIdsFrm;
import com.zy.explore.search.interfaces.vo.ArticleVO;
import com.zy.explore.search.interfaces.vo.PageVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.data.solr.core.query.Criteria;
import org.springframework.data.solr.core.query.HighlightOptions;
import org.springframework.data.solr.core.query.HighlightQuery;
import org.springframework.data.solr.core.query.Query;
import org.springframework.data.solr.core.query.SimpleHighlightQuery;
import org.springframework.data.solr.core.query.SimpleQuery;
import org.springframework.data.solr.core.query.result.HighlightEntry;
import org.springframework.data.solr.core.query.result.HighlightPage;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * 建类说明：搜索服务
 *
 * @author 中国印
 * @date 2022年02月12日 00:04:27
 */
@Slf4j
@Service
public class SearchService {

    private static final String SOLR_CORE = "test_core";

    @Resource
    private SolrTemplate solrTemplate;

    @Autowired
    private ArticleRepository articleRepository;

    public void batchInsert(List<Article> articles) {
        solrTemplate.saveBeans(SOLR_CORE, articles);
        solrTemplate.commit(SOLR_CORE);
    }

    public int deleteById(CommonIdFrm frm) {
        solrTemplate.deleteByIds(SOLR_CORE, frm.getId());
        solrTemplate.commit(SOLR_CORE);
        return 1;
    }

    public Article save(Article article) {
        solrTemplate.saveBean(SOLR_CORE, article);
        solrTemplate.commit(SOLR_CORE);
        return article;
    }

    public int deleteAll() {
        Query query = new SimpleQuery("*:*");
        solrTemplate.delete(SOLR_CORE, query);
        solrTemplate.commit(SOLR_CORE);
        return 1;
    }

    public List<ArticleVO> findAll() {
        List<ArticleVO> retList = Lists.newArrayList();
        List<Article> articles = Lists.newArrayList(articleRepository.findAll());
        if (CollectionUtils.isEmpty(articles)) {
            return retList;
        }
        articles.forEach(x -> retList.add(convertToVO(x)));
        return retList;
    }



    public ArticleVO findById(String id) {
        return convertToVO(solrTemplate.getById(SOLR_CORE, id, Article.class).orElse(null));
    }

    public List<ArticleVO> findByIds(CommonIdsFrm frm) {
        List<ArticleVO> retList = Lists.newArrayList();
        List<Article> articles = Lists.newArrayList(solrTemplate.getByIds(SOLR_CORE, frm.getIds(), Article.class));
        if (CollectionUtils.isEmpty(articles)) {
            return retList;
        }
        articles.forEach(x -> retList.add(convertToVO(x)));
        return retList;
    }

    public ArticleVO insert(ArticleSaveFrm frm) {
        frm.setId(UUID.fastUUID().toString().replace("-", ""));
        frm.setCreateTime(new Date());
        frm.setUpdateTime(new Date());
        // 将对象的用于搜索的字符串字段变量拼接到一个字段用来关键字搜索
        frm.setKeywords(frm.getTitle() + " " + frm.getSummary() + " " + frm.getTags());
        return convertToVO(save(convertFromFrm(frm)));
    }

    public ArticleVO update(ArticleSaveFrm frm) {
        ArticleVO exist = findById(frm.getId());
        frm.setUpdateTime(new Date());
        frm.setCreateTime(exist.getCreateTime());
        return convertToVO(save(convertFromFrm(frm)));
    }

    public List<ArticleVO> findList(ArticleQueryFrm frm) {
        // TODO
        return Lists.newArrayList();
    }

    /**
     * 方法说明：查询分页，高亮显示
     *
     * @param frm 查询参数
     * @return {@link PageVO<ArticleVO>}
     */
    public PageVO<ArticleVO> findPage(ArticleQueryFrm frm) {
        String keywords = frm.getKeywords();
        if(StringUtils.isBlank(keywords)){
            return new PageVO<>();
        }
        int pageNum = frm.getPageNum();
        int pageSize = frm.getPageSize();
        HighlightQuery query = new SimpleHighlightQuery();
        HighlightOptions highlightOptions = new HighlightOptions();
        highlightOptions.addField("title")
                .addField("summary")
                .addField("tags")
                .setSimplePrefix("<em style='color:red;'>")
                .setSimplePostfix("</em>");
        query.setHighlightOptions(highlightOptions);
        Criteria criteria = new Criteria("keywords").is(keywords);
        query.addCriteria(criteria);
        long offset = Long.parseLong(String.valueOf((pageNum - 1) * pageSize));
        query.setOffset(offset).setRows(pageSize);
        HighlightPage<Article> articlePage = solrTemplate.queryForHighlightPage(SOLR_CORE, query, Article.class);
        List<HighlightEntry<Article>> list = articlePage.getHighlighted();
        for (HighlightEntry<Article> entry : list) {
            Article article = entry.getEntity();
            List<HighlightEntry.Highlight> highlights = entry.getHighlights();
            for (HighlightEntry.Highlight highlight : highlights) {
                if ("title".equals(highlight.getField().getName())) {
                    article.setTitle(entry.getHighlights().get(0).getSnipplets().get(0));
                } else if ("summary".equals(highlight.getField().getName())){
                    article.setSummary(entry.getHighlights().get(0).getSnipplets().get(0));
                } else {
                    article.setTags(entry.getHighlights().get(0).getSnipplets().get(0));
                }
            }
        }
        List<ArticleVO> retList = Lists.newArrayList();
        List<Article> content = articlePage.getContent();
        if (!CollectionUtils.isEmpty(content)) {
            content.forEach(x -> retList.add(convertToVO(x)));
        }
        return PageVO.of(pageNum, pageSize, articlePage.getTotalElements(), retList);
    }

    private ArticleVO convertToVO(Article article) {
        return article == null ? null : DataBeanUtil.copyOf(article, ArticleVO.class, true);
    }

    private Article convertFromFrm(ArticleSaveFrm frm) {
        // 新增或修改时根据实际业务做参数校验 TODO
        return DataBeanUtil.copyOf(frm, Article.class, true);
    }
}
